package com.jason.common.video;

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 压缩视频，主要控制视频分辨率、帧率、编码格式和码率
 *
 * @author gzc
 * @since 2024/1/2 6:30
 **/
public class CompressedVideoTest {
    public static void main(String[] args) throws Exception {
        String inputVideoFilePath = "E:\\javacv-test\\SSIS-986-UC感觉新来的女社员很好搞定 利用前辈教育的立场来... 香水纯.mp4";
        String outputVideoFilePath = "E:\\javacv-test\\SSIS-986-UC-compressed111.mp4";
        compressedVideo(inputVideoFilePath, outputVideoFilePath,
                null, null, null, 5000);
    }

    public static void compressedVideo(String inputVideoFilePath,
                                       String outputVideoFilePath,
                                       Integer height,
                                       Integer width,
                                       Integer frameRate,
                                       Integer bitrate) throws Exception {
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputVideoFilePath);
        grabber.start();
        int lengthInVideoFrames = grabber.getLengthInVideoFrames();
        int lengthInAudioFrames = grabber.getLengthInAudioFrames();
        int total = lengthInAudioFrames + lengthInVideoFrames;
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputVideoFilePath, grabber.getAudioChannels());
        recorder.setImageWidth(grabber.getImageWidth());
        recorder.setImageHeight(grabber.getImageHeight());
        // 设置H264编码
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        // 设置视频格式
        recorder.setFormat("mp4");
        recorder.setFormat(grabber.getFormat());
        // 使用原始视频的码率，若需要则自行修改码率
        recorder.setVideoBitrate(bitrate);
        // 一秒内的帧数，帧率
//        recorder.setFrameRate(frameRate);
        // 设置音频通道数，与视频源的通道数相等
        recorder.setAudioChannels(grabber.getAudioChannels());
        if (frameRate != null) {
            recorder.setFrameRate(frameRate);
        } else {
            recorder.setFrameRate(grabber.getFrameRate());
        }
        recorder.setSampleRate(grabber.getSampleRate());
        recorder.setVideoBitrate(grabber.getVideoBitrate());
        recorder.setAspectRatio(grabber.getAspectRatio());
//        recorder.setAudioBitrate(grabber.getAudioBitrate());
        recorder.setAudioBitrate(128);
        recorder.setAudioOptions(grabber.getAudioOptions());
        recorder.setAudioCodec(grabber.getAudioCodec());

        //设置零延迟
        recorder.setVideoOption("tune", "fastdecode");
        // 快速
        recorder.setVideoOption("preset", "ultrafast");
//        recorder.setVideoOption("preset", "veryslow");
//        recorder.setVideoOption("preset", "veryslow");
        recorder.setVideoOption("threads", "12");
        recorder.setVideoOption("vsync", "2");

        recorder.start();
        Frame frame;
        int count = 0;
        Double doubleInt = 0.0D;
        while (grabber.grab() != null) {
            frame = grabber.grab();
            recorder.record(frame);
            count++;
            Double doubleValue = new BigDecimal(count).divide(new BigDecimal(total), 4, RoundingMode.FLOOR).multiply(new BigDecimal(100)).doubleValue();
            if (doubleInt.compareTo(0D) != 0 && doubleInt.compareTo(doubleValue) != 0) {
                System.out.println(doubleValue);
            }
            doubleInt = doubleValue;
        }
        recorder.stop();
        grabber.stop();
    }
}
